package cn.mandy.sysadmin.service.impl;

import cn.mandy.sysadmin.common.util.MandyTree;
import cn.mandy.sysadmin.constant.MandyConstant;
import cn.mandy.sysadmin.dao.MandyDictFrontEndDao;
import cn.mandy.sysadmin.dao.MandyRoleMenuDao;
import cn.mandy.sysadmin.dto.MandyAuthority;
import cn.mandy.sysadmin.dto.MandyDictFrontEnd;
import cn.mandy.sysadmin.dto.MandyMainMenu;
import cn.mandy.sysadmin.dto.MandyRoleResource;
import cn.mandy.sysadmin.mapper.*;
import cn.mandy.sysadmin.model.*;
import cn.mandy.sysadmin.service.MandyCacheService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;

//@Component("cacheService")
@Service
public class MandyCacheServiceImpl implements MandyCacheService {

    @Autowired
    MandyUserMapper mandyUserMapper;

    @Autowired
    MandyUserRoleMapper mandyUserRoleMapper;

    @Autowired
    MandyRoleMenuDao mandyRoleMenuDao;

    @Autowired
    MandyRoleMapper mandyRoleMapper;

    @Autowired
    MandyPermissionMapper permissionMapper;

    @Autowired
    MandyPermParamMapper mandyPermParamMapper;

    @Autowired
    MandyRolePermissionMapper mandyRolePermissionMapper;

    @Autowired
    MandyParameterMapper mandyParameterMapper;

    @Autowired
    MandyRolePermParamMapper mandyRolePermParamMapper;

    @Autowired
    MandyDictFrontEndDao mandyDictFrontEndDao;

    @Override
    @Cacheable(cacheNames = "getMandyUserByName", key = "#username")
    public MandyUser getMandyUserByName(String username){
        MandyUserExample mandyUserExample = new MandyUserExample();
        mandyUserExample.createCriteria().andUsernameEqualTo(username.trim());
        List<MandyUser> mandyUsers = mandyUserMapper.selectByExample(mandyUserExample);
        if (null == mandyUsers || mandyUsers.size() != 1){
            return null;
        }

        return mandyUsers.get(0);
    }

    @Override
    @CacheEvict(cacheNames = "getMandyUserByName", key = "#username")
    public void cacheEvictGetMandyUserByName(String username){
        return;
    }

    @Override
    @Cacheable(cacheNames = "listUserRolesByUserId", key = "#userId")
    public List<MandyUserRole> listUserRolesByUserId(Long userId){
        MandyUserRoleExample userRoleExample = new MandyUserRoleExample();
        userRoleExample.createCriteria()
                .andUserIdEqualTo(userId);

        return mandyUserRoleMapper.selectByExample(userRoleExample);
    }

    @Override
    @CacheEvict(cacheNames = "listUserRolesByUserId", key = "#userId")
    public void cacheEvictListUserRolesByUserId(Long userId){
        return;
    }

    @Override
    @CacheEvict(cacheNames = "listUserRolesByUserId", allEntries=true )
    public void cacheEvictListUserRolesEntries(){
        return;
    }

    @Override
    @Cacheable(cacheNames = "listMandyAuthorityByRoleId", key = "#roleId")
    public List<MandyAuthority>  listMandyAuthorityByRoleId(Long roleId){
        List<MandyRoleResource> mandyRolePermissions;
        mandyRolePermissions = mandyRoleMenuDao.getRoleMenuPermissionList(
                roleId, MandyConstant.AuditState.CHECKED);

        List<MandyAuthority> mandyAuthorities = new ArrayList<>() ;
        for (MandyRoleResource permission: mandyRolePermissions ) {
            if (MandyConstant.PermType.FUNCTION.equals(permission.getPermType())
                    && MandyConstant.YesOrNo.YES.equals(permission.getIzAllowed())) {
                MandyAuthority authority = new MandyAuthority();
                authority.setAuthority(permission.getName());
                mandyAuthorities.add(authority);
            }
        }

        return mandyAuthorities;
    }

    @Override
    @CacheEvict(cacheNames = "listMandyAuthorityByRoleId", key = "#roleId")
    public void cacheEvictListMandyAuthorityByRoleId(Long roleId){
        return;
    }

    //加上缓存
    @Override
    @Cacheable(cacheNames = "getRoleMainMenu")
    public List<MandyMainMenu> getRoleMainMenu(Long roleId) {
        List<MandyMainMenu> ret = new ArrayList<>();

        //对角色的状态进行确认，支持角色的禁用
        MandyRole role = mandyRoleMapper.selectByPrimaryKey(roleId);
        if (MandyConstant.AuditState.UNCHECKED.equals(role.getAuditState())){
            return ret;
        }

        List<MandyRoleResource>  roleResources = mandyRoleMenuDao.getRoleMenuPermissionList(roleId, MandyConstant.AuditState.CHECKED);
        for (MandyRoleResource permission: roleResources ) {
            if ( MandyConstant.YesOrNo.YES.equals(permission.getIzAllowed())
                    && ! MandyConstant.PermType.FUNCTION.equals(permission.getPermType()) ) {
                MandyMainMenu mainMenuItem = new MandyMainMenu();
                mainMenuItem.setId(permission.getId());
                mainMenuItem.setParentId(permission.getParentId());
                mainMenuItem.setComponentName(permission.getName());
                mainMenuItem.setTitle(permission.getTitle());
                mainMenuItem.setIconClass(permission.getIconClass());
                ret.add(mainMenuItem);
            }
        }
        return MandyTree.listToTree(ret);
    }

    @Override
    @CacheEvict(cacheNames = "getRoleMainMenu")
    public void cacheEvictGetRoleMainMenu(Long roleId){
        return;
    }


    @Override
    @Cacheable(value = "getRoleById")
    public MandyRole getRoleById(Long roleId) {
        return mandyRoleMapper.selectByPrimaryKey(roleId);
    }

    @Override
    @CacheEvict(value = "getRoleById")
    public void cacheEvictGetRoleById(Long roleId) { return; }

    //TODO 加缓存
    @Override
    @Cacheable(cacheNames = "getParameters")
    public List<MandyParameter>  getParameters(Long roleId, String requestUrl){
        //通过 requestUrl 找到 MandyPermission.id，要校验唯一性
        MandyPermissionExample mandyPermissionExample = new MandyPermissionExample();
        mandyPermissionExample.createCriteria().andNameEqualTo(requestUrl);
        List<MandyPermission> permissions =  permissionMapper.selectByExample(mandyPermissionExample);
        if (null == permissions || permissions.size() != 1){
            return null;
        }

        //获取permission 的参数, 如果无参, 直接返回 null
        Long permId = permissions.get(0).getId();
        MandyPermParamExample mandyPermParamExample = new MandyPermParamExample();
        List<MandyPermParam> mandyPermParams = mandyPermParamMapper.selectByExample(mandyPermParamExample);
        if (null == mandyPermParams || mandyPermParams.isEmpty()){
            return null;
        }

        //通过 roleId, permissionId 获得 MandyRolePermission.id
        //要校验审核状态, 允许标志
        MandyRolePermissionExample mandyRolePermissionExample = new MandyRolePermissionExample();
        mandyRolePermissionExample.createCriteria()
                .andAuditStateEqualTo(MandyConstant.AuditState.CHECKED)
                .andIzAllowedEqualTo(MandyConstant.YesOrNo.YES)
                .andRoleIdEqualTo(roleId)
                .andPermissionIdEqualTo(permId);
        List<MandyRolePermission> mandyRolePermissions = mandyRolePermissionMapper.selectByExample(mandyRolePermissionExample);
        if (null == mandyRolePermissions || mandyRolePermissions.size() != 1){
            return null;
        }

        //获得所有permission 对应的参数定义
        List<Long> paramIds = new ArrayList<>();
        for (MandyPermParam permParam: mandyPermParams) {
            paramIds.add(permParam.getParameterId());
        }
        MandyParameterExample mandyParameterExample = new MandyParameterExample();
        mandyParameterExample.createCriteria().andIdIn(paramIds);
        List<MandyParameter> ret = mandyParameterMapper.selectByExample(mandyParameterExample);

        //获得Role对应的参数值设置, mandyRolePermParams 可能是空的
        MandyRolePermParamExample mandyRolePermParamExample = new MandyRolePermParamExample();
        mandyRolePermParamExample.createCriteria().andRolePermissionIdEqualTo(mandyRolePermissions.get(0).getId());
        List<MandyRolePermParam>  mandyRolePermParams = mandyRolePermParamMapper.selectByExample(mandyRolePermParamExample);

        //返回ret, 用Role设置过的值覆盖默认值
        //换言之, 没有设置过的就用默认值了
        if (null == mandyRolePermParams || mandyRolePermParams.isEmpty()){
            return ret;
        }

        for (MandyParameter param: ret) {
            for (MandyRolePermParam paramSetting : mandyRolePermParams) {
                if (param.getId().equals(paramSetting.getParameterId())){
                    param.setDefaultValue(paramSetting.getValue());
                }
            }
        }

        return ret;
    }

    @Override
    @CacheEvict(cacheNames = "getParameters", allEntries=true )
    public void cacheEvictGetParametersEntries() {
        return;
    }

    //另一种做法：要改成修改成常量,硬编码,可借用SQL语句自动生成。参考 MandyConstant
    @Override
    @Cacheable(cacheNames = "dictList")
    public List<MandyDictFrontEnd>  dictList() {
        return mandyDictFrontEndDao.getDictList();
    }

}
